package com.matezk.sael.tencent;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

import com.matezk.sael.R;
import com.matezk.sael.beans.Action;
import com.matezk.sael.hardware.GpioControl;
import com.tencent.iot.explorer.device.java.data_template.TXDataTemplateDownStreamCallBack;
import com.tencent.iot.explorer.device.java.mqtt.TXMqttRequest;
import com.tencent.iot.hub.device.java.core.common.Status;
import com.tencent.iot.hub.device.java.core.dynreg.TXMqttDynreg;
import com.tencent.iot.hub.device.java.core.dynreg.TXMqttDynregCallback;
import com.tencent.iot.hub.device.java.core.mqtt.TXMqttActionCallBack;

import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;

import static com.tencent.iot.explorer.device.java.data_template.TXDataTemplateConstants.TemplateSubTopic.ACTION_DOWN_STREAM_TOPIC;
import static com.tencent.iot.explorer.device.java.data_template.TXDataTemplateConstants.TemplateSubTopic.EVENT_DOWN_STREAM_TOPIC;
import static com.tencent.iot.explorer.device.java.data_template.TXDataTemplateConstants.TemplateSubTopic.PROPERTY_DOWN_STREAM_TOPIC;
import static com.tencent.iot.explorer.device.java.data_template.TXDataTemplateConstants.TemplateSubTopic.SERVICE_DOWN_STREAM_TOPIC;

public class TencentService extends Service {
    private static final String TAG = TencentService.class.getSimpleName();

    private static final String PRODUCT_ID = "XTVV6EY5NB";
    private static final String PRODUCT_KEY = "ups4NpYexhzLkMoT2xRcNYY8";
    private static final String DEVICE_NAME = "AD20240406001";

    private BlockingQueue<JSONObject> reportQueue = new LinkedBlockingDeque<>(10);

    private TencentDataTemplateClient templateClient;
    private GpioControl gpioControl = GpioControl.getInstance();

    private static AtomicInteger requestID = new AtomicInteger(0);


    private class ReportThread extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    JSONObject object = reportQueue.take();
                    if (null != templateClient && templateClient.isConnected()) {
                        templateClient.propertyReport(object, null);
                    }
                } catch (Exception e) {
                    Log.e(TAG, "上报失败", e);
                }
            }
        }
    }

    public class TencentMqttThread extends Thread {
        @Override
        public void run() {
            TXMqttDynreg dynreg = new TXMqttDynreg(PRODUCT_ID, PRODUCT_KEY, DEVICE_NAME, new TXMqttDynregCallback() {
                @Override
                public void onGetDevicePSK(String devicePsk) {
                    Log.d("mqtt", devicePsk);

                    qcloudStart(PRODUCT_ID, readProductModel(), DEVICE_NAME, devicePsk);
                }

                @Override
                public void onGetDeviceCert(String deivceCert, String devicePriv) {

                }

                @Override
                public void onFailedDynreg(Throwable cause, String errMsg) {

                }

                @Override
                public void onFailedDynreg(Throwable cause) {

                }
            });
            dynreg.doDynamicRegister();
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        new TencentMqttThread().start();
        new ReportThread().start();

        // 注册广播接收器
        ServiceBroadcastReceiver receiver = new ServiceBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(Action.Report_Power_Switch);
        registerReceiver(receiver, filter);

        filter = new IntentFilter();
        filter.addAction(Action.Report_Power_Type);
        registerReceiver(receiver, filter);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    public class ActionCallBack extends TXMqttActionCallBack {

        @Override
        public void onConnectCompleted(Status status, boolean reconnect, Object userContext, String msg) {

        }

        @Override
        public void onConnectionLost(Throwable cause) {

        }

        @Override
        public void onDisconnectCompleted(Status status, Object userContext, String msg) {

        }
    }

    public class DownStreamCallBack extends TXDataTemplateDownStreamCallBack {
        @Override
        public void onReplyCallBack(String msg) {
            Log.d("msg", msg);
        }

        @Override
        public void onGetStatusReplyCallBack(JSONObject data) {
            try {
                Log.d("data", data.toString(4));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public JSONObject onControlCallBack(JSONObject msg) {
            try {
                return new JSONObject().put("code", 0).put("status", "succ");
            } catch (JSONException e) {
                return null;
            }
        }

        @Override
        public JSONObject onActionCallBack(String actionId, JSONObject params) {
            try {
                if ("pswitch".equals(actionId)) {
                    int out = params.getInt("out");
                    gpioControl.changePowerType(1 == out ? GpioControl.PowerType.AQD : GpioControl.PowerType.SD, powerType -> {
                        Intent intent = new Intent();
                        intent.setAction(Action.Update_Power_Type);
                        intent.putExtra("type", powerType);
                        sendBroadcast(intent);
                        reportQueue.add(new JSONObject().put("out", powerType.ordinal()));
                    });
                } else if ("power".equals(actionId)) {
                    int state = params.getInt("power");
                    gpioControl.changePowerState(1 == state ? GpioControl.PowerState.ON : GpioControl.PowerState.OFF, powerState -> {
                        Intent intent = new Intent();
                        intent.setAction(Action.Update_Power_Switch);
                        intent.putExtra("state", powerState);
                        sendBroadcast(intent);
                        reportQueue.add(new JSONObject().put("pswitch_state", powerState.ordinal()));
                    });
                }

                JSONObject result = new JSONObject();
                result.put("code", 0);
                result.put("status", "succ");
                if (null != params) {
                    result.put("response", params);
                }
                return result;
            } catch (JSONException e) {
                return new JSONObject();
            }
        }

        @Override
        public void onUnbindDeviceCallBack(String msg) {

        }
    }

    private class ServiceBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            try {
                if (Action.Report_Power_Type.equals(intent.getAction())) {
                    GpioControl.PowerType type = (GpioControl.PowerType)intent.getSerializableExtra("type");
                    reportQueue.add(new JSONObject().put("out", type.ordinal()));
                } else if (Action.Report_Power_Switch.equals(intent.getAction())) {
                    GpioControl.PowerState state = (GpioControl.PowerState)intent.getSerializableExtra("state");
                    reportQueue.add(new JSONObject().put("pswitch_state", state.ordinal()));
                }
            } catch (Exception e) {
                Log.e(TAG, "异步上报异常", e);
            }
        }
    }

    private void qcloudStart(String productId, String json, String deviceName, String devicePsk) {
        templateClient = new TencentDataTemplateClient(productId, json, deviceName, devicePsk, new ActionCallBack(), new DownStreamCallBack());

        MqttConnectOptions options = new MqttConnectOptions();
        options.setConnectionTimeout(8);
        options.setKeepAliveInterval(240);
        options.setAutomaticReconnect(true);
        TXMqttRequest mqttRequest = new TXMqttRequest("connect", requestID.getAndIncrement());
        templateClient.connect(options, mqttRequest);
        subscribeTopic(templateClient);
    }

    private void subscribeTopic(TencentDataTemplateClient connection) {
        if(Status.OK != connection.subscribeTemplateTopic(PROPERTY_DOWN_STREAM_TOPIC, 0)){
            Log.e(TAG, "subscribeTopic: subscribe property down stream topic failed!");
        }
        if(Status.OK != connection.subscribeTemplateTopic(EVENT_DOWN_STREAM_TOPIC, 0)){
            Log.e(TAG, "subscribeTopic: subscribe event down stream topic failed!");
        }
        if(Status.OK != connection.subscribeTemplateTopic(ACTION_DOWN_STREAM_TOPIC, 0)){
            Log.e(TAG, "subscribeTopic: subscribe action down stream topic failed!");
        }
        if(Status.OK != connection.subscribeTemplateTopic(SERVICE_DOWN_STREAM_TOPIC, 0)){
            Log.e(TAG, "subscribeTopic: subscribe service down stream topic failed!");
        }
    }


    // 读取产品物模型
    private String readProductModel() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.struct)));
        StringBuilder sb = new StringBuilder();
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            return null;
        }
        return sb.toString();
    }
}
